﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Agility.Web.Repositories.EntityFramework;
using Agility.Web.Models.DomainModel;

namespace Agility.Testing.Web.Requirements
{
    [TestFixture]
    public class EntityFrameworkRepositoryBaseTests
    {
        EpicRepository epicRepository;
        AgilityRequirementsModelEntities entities;
        Epic target;

        [TestFixtureSetUp]
        public void SetupTestFixture()
        {
            entities = new AgilityRequirementsModelEntities();
        }

        [TestFixtureTearDown]
        public void TeardownTestFixture()
        {
            entities.Dispose();
        }

        [SetUp]
        public void SetupTest()
        {
            // Arrange
            target = Epic.CreateEpic(Guid.NewGuid(), "Epic1", "Epic1 Description", DateTime.Today, "Dave");
            Epic e2 = Epic.CreateEpic(Guid.NewGuid(), "Epic2", "Epic2 Description", DateTime.Today, "Dave");
            Epic e3 = Epic.CreateEpic(Guid.NewGuid(), "Epic3", "Epic3 Description", DateTime.Today, "Dave");
            entities.Epics.AddObject(target);
            entities.Epics.AddObject(e2);
            entities.Epics.AddObject(e3);
            entities.SaveChanges();

            epicRepository = new EpicRepository(entities);
        }

        [TearDown]
        public void TeardownTest()
        {
            foreach (Epic epic in entities.Epics)
            {
                entities.Epics.DeleteObject(epic);
            }
            entities.SaveChanges();
        }

        [Test]
        [Category("UnitTest")]
        public void TestGetEpics()
        {
            // Act
            IQueryable<Epic> actual = epicRepository.GetEntities();

            // Assert
            Assert.AreEqual(entities.Epics.Count(), actual.Count());
        }

        [Test]
        [Category("UnitTest")]
        public void TestInsertEpic()
        {
            // Arrange
            Epic epic = Epic.CreateEpic(Guid.NewGuid(), "New Epic", "Descriptive text", DateTime.Today, "Me");
            int initialCount = entities.Epics.Count();

            // Act
            epicRepository.Insert(epic);
            epicRepository.Save();

            // Assert
            Assert.AreEqual(initialCount + 1, entities.Epics.Count());
        }

        // TODO: provide a version of this test with an entity that has a timestamp attribute
        [Test]
        [Category("UnitTest")]
        [ExpectedException("System.InvalidOperationException")]
        public void TestUpdateEpic()
        {
            string title = "New Title";
            string description = "New Description";

            // Act
            this.target.Title = title;
            this.target.Description = description;
            epicRepository.Update(target);
        }

        [Test]
        [Category("UnitTest")]
        public void TestUpdateEpicWithOriginal()
        {
            string title = "New Title";
            string description = "New Description";
            Epic original = entities.Epics.Single(e => e.Id == target.Id);

            // Act
            this.target.Title = title;
            this.target.Description = description;
            epicRepository.Update(target, original);
            epicRepository.Save();
            
            // Assert
            Assert.AreEqual(title, entities.Epics.Single(e => e.Id == target.Id).Title);
            Assert.AreEqual(description, entities.Epics.Single(e => e.Id == target.Id).Description);
        }

        [Test]
        [Category("UnitTest")]
        public void TestDeleteEpic()
        {
            // Act
            epicRepository.Delete(target);
            epicRepository.Save();

            // Assert
            Assert.IsNull(entities.Epics.SingleOrDefault(e => e.Id == target.Id));
        }
    }
}
